﻿using System;
using System.Collections.Generic;
using System.Reflection;
namespace Nereus
{
    using Power;
    using Attributes;
    public class DefaultNBuilder : INBuilder
    {
        public virtual INClassContent[] BuildClassContent(string[] assemblyPathArray)
        {
            var _allNClass = new List<NClassContent>();
            var nAssemblies = new List<Assembly>();
            if (assemblyPathArray == null || assemblyPathArray.Length <= 0)
            {
                var assemblies = new Assembly[] { Assembly.GetEntryAssembly() };
            }
            else
            {
                foreach (var item in assemblyPathArray)
                {
                    nAssemblies.Add(AppDomain.CurrentDomain.Load(item));
                }
            }
            var allTypes = new List<Type>();
            foreach (var item in nAssemblies)
            {
                allTypes.AddRange(item.GetTypes());
            }
            foreach (var type in allTypes)
            {
                var nClassAttributes = type.GetCustomAttributes<NClassAttribute>();
                foreach (var nClassAttribute in nClassAttributes)
                {
                    var nClass = new NClassContent()
                    {
                        Code = nClassAttribute.Code,
                        Description = nClassAttribute.Description,
                        Name = nClassAttribute.Name,
                    };
                    nClass.Methods = BuildMethodContent(type);
                    _allNClass.Add(nClass);
                }
            }
            return _allNClass.ToArray();
        }

        public virtual INMethodContent[] BuildMethodContent(Type classType)
        {
            var classMethods = classType.GetMethods();
            var nMethods = new List<NMethodContent>();
            foreach (var method in classMethods)
            {
                var nMethodAttribute = method.GetNAttribute<NMethodAttribute>();
                if (nMethodAttribute == null)
                {
                    continue;
                }
                if (nMethodAttribute.Enable)
                {
                    var arguments = method.GetGenericArguments();

                    var nAction = new NMethodContent()
                    {
                        ActionCode = string.IsNullOrWhiteSpace(nMethodAttribute.Code) ? method.Name : nMethodAttribute.Code,
                        ArgumentProperties = BuildPropertyContent(nMethodAttribute.Argument ?? arguments[0]),
                        Description = nMethodAttribute.Description,
                        Method = nMethodAttribute.Method,
                        Name = nMethodAttribute.Name,
                        ResultExplain = nMethodAttribute.ResultExplain,
                        ResultProperties = BuildPropertyContent(nMethodAttribute.Result),
                        Uri = nMethodAttribute.Uri
                    };
                    nMethods.Add(nAction);
                }
            }
            return nMethods.ToArray();
        }

        public virtual INPropertyContent[] BuildPropertyContent(Type mainPropertyType)
        {
            if (mainPropertyType == null)
            {
                return null;
            }
            var nActionProperties = mainPropertyType.GetProperties();
            var nProperties = new List<NPropertyContent>();
            foreach (var property in nActionProperties)
            {
                var nPropertyAttribute = property.GetCustomAttribute<NPropertyAttribute>();

                var nProperty = new NPropertyContent()
                {
                    Name = property.Name,
                    Type = property.PropertyType.Name,
                };
                if (nPropertyAttribute != null)
                {
                    string enumDescription = string.Empty;
                    if (nPropertyAttribute.EnumType != null)
                    {
                        var names = nPropertyAttribute.EnumType.GetEnumNames();
                        var values = new List<int>();
                        foreach (var item in nPropertyAttribute.EnumType.GetFields(BindingFlags.Static | BindingFlags.Public))
                        {
                            values.Add(Convert.ToInt32(item.GetValue(null)));
                        }
                        for (var i = 0; i < names.Length; i++)
                        {
                            enumDescription += names[i] + "-" + values[i].ToString() + ",";
                        }
                    }
                    nProperty.Description = nPropertyAttribute.Description + enumDescription.TrimEnd(',');
                }

                if (property.PropertyType.IsGenericType)
                {
                    nProperty.SubProperties = BuildPropertyContent(property.PropertyType.GetGenericArguments()[0]);
                }
                nProperties.Add(nProperty);
            }
            return nProperties.ToArray();
        }
    }
}
